home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
winsock
/
ircii2-6.zip
/
SRC\IRCII-2.6\SOURCE\TRANSLAT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-12-28
|
10KB
|
434 lines
/*
* translat.c: Stuff for handling character translation tables
* and a digraph entry facility. Support an international IRC!
*
* I listen to Sex Pistols, so I assume everyone in this world,
* and more specifically, all servers, are using ISO 8859/1
* (Latin-1). And in case of doubt, please consult Jarkko 'Wiz'
* Oikarinen's document "Internet Relay Chat Protocol" (doc/Comms
* in the ircd package), paragraph 2.2. Besides, all of the sane
* world has already converted to this set. (X-Windows, Digital,
* MS-Windows, etc.)
* If someone please would forward me some documentation on other
* international sets, like 8859/2 - 8859/10 etc, please do so!
* Moreover, feedback on the tables in the definition files would
* be greatly appreciated!
* Another idea, to be implemented some beautiful day, would be
* to add transliteration of the Kanji/Katakana sets used in
* the far east. 8-)
* Tomten <tomten@solace.hsh.se> / <tomten@lysator.liu.se>
*/
#ifndef lint
static char rcsid[] = "@(#)$Id: translat.c,v 1.6 1994/07/02 02:32:13 mrg Stab $";
#endif
#include "irc.h"
#include "vars.h"
#include "translat.h"
#include "ircaux.h"
#include "window.h"
#include "screen.h"
#include "output.h"
#if defined(__STDC__) || defined(__cplusplus)
static unsigned char my_getarg(char **args);
#else
static unsigned char my_getarg();
#endif
/* Globals */
unsigned char transToClient[256]; /* Server to client translation. */
unsigned char transFromClient[256]; /* Client to server translation. */
char translation = 0; /* 0 for transparent (no) translation. */
char digraph_changed = 0;
/*
* dig_table_lo[] and dig_table_hi[] contain the character pair that
* will result in the digraph in dig_table_di[]. To avoid searching
* both tables, I take the lower character of the pair, and only
* search dig_table_lo[]. Thus, dig_table_lo[] must always contain
* the lower character of the pair.
*
* The digraph tables are based on those in the excellent editor Elvis,
* with some additions for those, like me, who are used to VT320 or
* VT420 terminals.
*/
#define DiLo(x) x,
#define DiHi(x)
#define DiDi(x)
/*
* Digraph tables. Note that, when adding a new digraph, the character
* of the pair with the lowest value, *must* be in the DiLo column.
* The higher of the pair goes in DiHi, and the digraph itself in DiDi.
*/
unsigned char dig_table_lo[DIG_TABLE_SIZE] =
{
#include "digraph.inc"
0
};
#undef DiLo
#undef DiHi
#undef DiDi
#define DiLo(x)
#define DiHi(x) x,
#define DiDi(x)
unsigned char dig_table_hi[DIG_TABLE_SIZE] =
{
#include "digraph.inc"
0
};
#undef DiLo
#undef DiHi
#undef DiDi
#define DiLo(x)
#define DiHi(x)
#define DiDi(x) x,
unsigned char dig_table_di[DIG_TABLE_SIZE] =
{
#include "digraph.inc"
0
};
/*
* enter_digraph: The BIND function ENTER_DIGRAPH.
*/
#if defined(__STDC__) || defined(__cplusplus)
void enter_digraph(unsigned char key, char *ptr)
#else
void enter_digraph(key, str)
unsigned char key;
char *str;
#endif
{
current_screen->digraph_hit = 1; /* Just stuff away first character. */
}
/*
* get_digraph: Called by edit_char() when a digraph entry is activated.
* Looks up a digraph given char c1 and the global char
* current_screen->digraph_hit.
*/
#if defined(__STDC__) || defined(__cplusplus)
unsigned char get_digraph(unsigned char c1)
#else
unsigned char get_digraph(c1)
unsigned char c1;
#endif
{
int i = 0;
unsigned char c,
c2 = current_screen->digraph_first;
current_screen->digraph_hit = 0;
if (c1 > c2) /* Make sure we have the lowest one in c1. */
c = c1, c1 = c2, c2 = c;
while (dig_table_lo[i])
{ /* Find digraph and return it. */
if ((dig_table_lo[i] == c1) && (dig_table_hi[i] == c2))
return dig_table_di[i];
i++;
}
return 0; /* Failed lookup. */
}
/*
* set_translation: Called when the TRANSLATION variable is SET.
* Attempts to load a new translation table.
*/
#if defined(__STDC__) || defined(__cplusplus)
void set_translation(char *tablename)
#else
void set_translation(tablename)
char *tablename;
#endif
{
FILE *table;
unsigned char temp_table[512];
char *filename = (char *) 0;
int inputs[8];
int j,
c = 0;
tablename = upper(tablename);
/* Check for transparent mode; ISO-8859/1, Latin-1 */
if (!strcmp("LATIN_1", tablename))
{
translation = 0;
return;
}
/* Else try loading the translation table from disk. */
malloc_strcpy(&filename, TRANSLATION_PATH);
malloc_strcat(&filename, tablename);
if ( !(table = fopen(filename, "r")) )
{
say("Cannot open character table definition \"%s\" !",
tablename);
set_string_var(TRANSLATION_VAR, (char *) 0);
new_free(&filename);
return;
}
/* Any problems in the translation tables between hosts are
* almost certain to be caused here.
* many scanf implementations do not work as defined. In particular,
* scanf should ignore white space including new lines (many stop
* at the new line character, hence the fgets and sscanf workaround),
* many fail to read 0xab as a hexadecimal number (failing on the
* x) despite the 0x being defined as optionally existing on input,
* and others zero out all the output variables if there is trailing
* non white space in the format string which doesn't appear on the
* input. Overall, the standard I/O libraries have a tendancy not
* to be very standard.
*/
while (fgets(buffer, 80, table))
{
sscanf(buffer, "0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x",
inputs+0, inputs+1, inputs+2, inputs+3,
inputs+4, inputs+5, inputs+6, inputs+7);
for (j = 0; j<8; j++)
temp_table[c++] = (unsigned char) inputs[j];
}
fclose(table);
new_free(&filename);
if (c == 512)
{
for (c = 0; c <= 255; c++)
{
transToClient[c] = temp_table[c];
transFromClient[c] = temp_table[c | 256];
}
translation = 1;
}
else
{
say("Error loading translation table \"%s\" !", tablename);
set_string_var(TRANSLATION_VAR, (char *) 0);
}
}
/*
* digraph: The /DIGRAPH command with facilities.
* This routine is *NOT* finished yet.
*/
#if defined(__STDC__) || defined(__cplusplus)
void digraph(char *command, char *args)
#else
void digraph(command, args)
char *command,
*args;
#endif
{
char *arg;
u_char c1,
c2 = '\0',
c3 = '\0';
int len,
i;
if ((arg = next_arg(args, &args)) && (*arg == '-'))
{
arg++;
if ((len = strlen(arg)) == 0)
{
say("Unknown or missing flag.");
return;
}
if (my_strnicmp(arg, "add", len) == 0)
{
/*
* Add a digraph to the table.
* I *know*. This *is* a kludge.
*/
if ((i = strlen((char *)dig_table_lo)) ==
DIG_TABLE_SIZE - 1)
say("Sorry, digraph table full.");
else
{
while ((c1 = my_getarg(&args)) &&
(c2 = my_getarg(&args)) &&
(c3 = my_getarg(&args)))
{
/* Pass c1 to get_digraph() */
current_screen->digraph_first = c1;
if (get_digraph(c2) == 0)
{
dig_table_di[i] = c3;
/* Make sure c1 <= c2 */
if (c1 > c2)
c3 = c1, c1 = c2, c2 = c3;
dig_table_lo[i] = c1;
dig_table_hi[i] = c2;
i++;
dig_table_lo[i] =
dig_table_hi[i] =
dig_table_di[i] =
(unsigned char) 0;
digraph_changed = 1;
say("Digraph added to table.");
}
else
{
say("Digraph already defined in table.");
break;
}
}
if (!c2 || !c3)
say("Unknown or missing argument.");
}
}
else if (my_strnicmp(arg, "remove", len) == 0)
{
/* Remove a digraph from the table. */
if ((i = strlen((char *)dig_table_lo)) == 0)
say("Digraph table is already empty.");
else
{
if ((c1 = my_getarg(&args)) &&
(c2 = my_getarg(&args)))
{
i = 0;
if (c1 > c2)
c3 = c1, c1 = c2, c2 = c3;
while (dig_table_lo[i])
{
if ((dig_table_lo[i] == c1) &&
(dig_table_hi[i] == c2))
/*
* strcpy() is not guaranteed for
* overlapping copying, but this one
* is high -> low. Ought to be fixed.
*/
/* re-indent this block - phone, jan 1993. */
{
strcpy(((char *)dig_table_lo + i),
(char *)(dig_table_lo + (i + 1)));
strcpy((char *)(dig_table_hi + i),
(char *)(dig_table_hi + (i + 1)));
strcpy((char *)(dig_table_di + i),
(char *)(dig_table_di + (i + 1)));
digraph_changed = 1;
put_it("Digraph removed from table.");
return;
}
/* much better */
i++;
}
say("Digraph not found.");
}
}
}
else if (my_strnicmp(arg, "clear", len) == 0)
{
/* Clear digraph table. */
dig_table_lo[0] = dig_table_hi[0] = dig_table_di[0] =
(unsigned char) 0;
digraph_changed = 1;
say("Digraph table cleared.");
}
else
say("Unknown flag.");
}
else
{
/* Display digraph table. */
char buffer1[8];
char buffer2[192];
say("Digraph table:");
buffer2[0] = (char) 0;
i = 0;
while(dig_table_lo[i])
{
sprintf(buffer1, "%c%c %c ", dig_table_lo[i],
dig_table_hi[i], dig_table_di[i]);
strcat(buffer2, buffer1);
if ((++i % 10) == 0)
{
put_it(buffer2);
buffer2[0] = (char) 0;
}
}
if (buffer2[0])
put_it(buffer2);
sprintf(buffer2, "%d digraphs listed.", i);
say(buffer2);
}
}
static unsigned char
#if defined(__STDC__) || defined(__cplusplus)
my_getarg(char **args)
#else
my_getarg(args)
char **args;
#endif
{
unsigned char *arg;
arg = (unsigned char *)next_arg(*args, args);
if (!args || !*args)
return '\0';
/* Don't trust isdigit() with 8 bits. */
if ((*arg <= '9') && (*arg >= '0'))
{
unsigned char i = *arg & 0x0f;
while ( *(++arg) )
i = (i * 10) + (*arg & 0x0f);
return i;
}
else if ( (*arg == '!') && (*(arg + 1)) )
return *(arg + 1) | 0x80;
return *arg;
}
#if defined(__STDC__) || defined(__cplusplus)
void save_digraphs(FILE *fp)
#else
void save_digraphs(fp)
FILE *fp;
#endif
{
if (digraph_changed)
{
int i = 0;
char *command = "\nDIGRAPH -ADD ";
fprintf(fp, "DIGRAPH -CLEAR");
fprintf(fp, command);
while(1)
{
fprintf(fp, "%d %d %d ", dig_table_lo[i],
dig_table_hi[i], dig_table_di[i]);
if (!dig_table_lo[++i])
break;
if (!(i % 5))
fprintf(fp, command);
}
fputc('\n', fp);
}
}